import * as cc from "cc"
import { IState } from "./IState";

export class StateMachine {


    private mapState: { [key: number]: IState } = null;

    private curState: IState = null;

    constructor() {
        this.mapState = {};
        this.curState = null;
    }

    /**清理状态 */
    clear(){
        this.stopState();
        this.mapState = {};
    }

    /**
     * 注册一个状态
     * @param state 要注册的状态
     * @returns 成功返回true，如果此状态ID已存在或状态为NULL，则返回false
     */
    public registState(state: IState): boolean {

        if (state == null) {
            cc.warn("StateMachine::RegistState->state is null");
            return false;
        }

        if (this.mapState[state.getId()]) {
            cc.warn("StateMachine::RegistState->state had exist! state id=" + state.getId());
            return false;
        }

        this.mapState[state.getId()] = state;

        return true;
    }

    public getState(id: number) {
        return this.mapState[id];
    }

    /**
     * 停止当前正在运行的状态, 切换到空状态
     */
    public stopState(): void {
        if (null == this.curState) {
            return;
        }

        this.curState.onLeave(null);

        this.curState = null;
    }

    /// <summary>
    /// 取消状态的注册
    /// </summary>
    /// <param name="iStateID">要取消的状态ID</param>
    /// <returns>如果找不到状态或状态正在运行，则会返回false</returns>
    public cancelState(id: number): boolean {
        if (!this.mapState[id]) {
            return false;
        }

        if (null != this.curState && this.curState.getId() == id) {
            return false;
        }
        return delete this.mapState[id];
    }

    /**在切换状态之间回调 */
    public betweenSwitchStateCallBack: (from: IState, to: IState) => void;

    /**
     * 切换状态
     * @param newStateId 要切换的新状态
     * @returns 如果找不到新的状态，或者新旧状态一样，返回false
     */
    public changeState(newStateId: number): boolean {
        //状态一样，不做转换//
        if (null != this.curState && this.curState.getId() == newStateId) {
            return false;
        }

        let newState: IState = this.mapState[newStateId];
        if (null == newState) {
            return false;
        }

        let oldState: IState = this.curState;

        if (null != oldState) {
            oldState.onLeave(newState);
        }

        if (this.betweenSwitchStateCallBack != null) this.betweenSwitchStateCallBack(oldState, newState);

        this.curState = newState;

        if (null != newState) {
            newState.onEnter(this, oldState);
        }

        return true;
    }

    /**获取当前状态 */
    public getCurState<T extends IState>(): T {
        return <T>this.curState;
    }

    /**
     * 获取当前状态ID
     */
    public getCurStateID(): number {
        return (null == this.curState) ? 0 : this.curState.getId();
    }

    /**
     * 判断当前是否在某个状态下
     * @param id 状态id
     */
    public isInState(id: number): boolean {
        if (null == this.curState) {
            return false;
        }

        return this.curState.getId() == id;
    }

    /**每帧的更新回调 */
    public onUpdate(dt: number): void {
        if (null != this.curState) {
            this.curState.onUpdate(dt);
        }
    }

}